def get_stock_industry_stocks(symbol, category_type='ci', date='20230801'):
    """
    根据股票代码和分类类型返回对应行业的成分股列表，
    并打印详细的所属行业信息（含中文名称）。
    
    参数：
    ----------
    symbol : str 
        股票代码，例如 '300033.SZ'
    category_type : str 
        行业分类类型，可选值：
        - 't'  : 同花顺行业 (industryid)
        - 's'  : 申万行业 (s_industryid)
        - 'c'  : 中信行业 (c_industryid)
        - 'ci' : 中信行业 (ci_industryid)
        - 'gi' : 全球行业分类 (gi_industryid)
    date : str 
        查询日期，格式 'YYYYMMDD'
        
    返回：
    ----------
    list[str]
        行业成分股代码列表
    """

    # 1️⃣ 获取股票所属行业代码信息
    industry_info = get_symbol_industry(symbol, date=date)
    
    # 各体系字段映射
    category_map = {
        't':  ('同花顺行业', ['industryid1', 'industryid2', 'industryid3']),
        's':  ('申万行业',   ['s_industryid1', 's_industryid2', 's_industryid3']),
        'c':  ('中信行业',   ['c_industryid', 'c_industryid2']),
        'ci': ('中信行业',   ['ci_industryid1', 'ci_industryid2', 'ci_industryid3']),
        'gi': ('全球行业',   ['gi_industryid1', 'gi_industryid2', 'gi_industryid3', 'gi_industryid4']),
    }

    if category_type not in category_map:
        raise ValueError(f"未知分类类型: {category_type}，可选值: {list(category_map.keys())}")
    
    category_name, fields = category_map[category_type]

    # 2️⃣ 获取行业中文名映射表（只针对当前体系）
    relate_type = f"{fields[0]}"  # 例如 "ci_industryid1"
    try:
        industry_relate_df = get_industry_relate(date=date, types=relate_type)
    except Exception:
        industry_relate_df = None

    # 3️⃣ 构造行业路径
    industry_path = []
    for f in fields:
        val = getattr(industry_info, f, None)
        if val:
            # 查询中文名
            name = None
            if industry_relate_df is not None:
                match = industry_relate_df[industry_relate_df['industry_symbol'] == val]
                if not match.empty:
                    name = match.index[0]  # index 是行业中文名
            if name:
                industry_path.append(f"{f}={val}（{name}）")
            else:
                industry_path.append(f"{f}={val}")
    
    # 取第一个层级代码作为行业成分股查询代码
    industry_code = getattr(industry_info, fields[0])

    # 4️⃣ 打印行业信息
    print(f"【股票代码】{symbol}")
    print(f"【分类类型】{category_type}（{category_name}）")
    print("【所属行业路径】")
    for p in industry_path:
        print("  -", p)
    print(f"【用于成分股提取的行业代码】{industry_code}\n")

    # 5️⃣ 获取成分股
    index_list = get_industry_stocks(industry_code, date)
    
    print(f"【成分股数量】{len(index_list)}")
    
    return index_list

def txfx(code, statDate='2025q1'):
    df = get_fundamentals(
        query(
            income.symbol,
            income.report_date,
            income.stat_date,
            income.operating_income,
            income.net_profit,
            income.operations_costs,
            income.operations_taxes_and_surcharges,
            income.sales_fee,
            income.manage_fee,
            income.financial_expenses,
            income.impairment_loss_on_assets,
            income.fv_chg_income,
            income.investment_income,
            income.profit_from_operations,
            income.profit_before_tax,
            income.minus_income_tax_expenses,
            income.net_profit
        ).filter(
            income.symbol == code,
            income.reporttypecode == 'HB'
        ),
        statDate=statDate
    )

    if df.empty:
        return None

    base = df['income_stat_operating_income'].iloc[0]
    cols = [
        'income_stat_operating_income',
        'income_stat_operations_costs',
        'income_stat_operations_taxes_and_surcharges',
        'income_stat_sales_fee',
        'income_stat_manage_fee',
        'income_stat_financial_expenses',
        'income_stat_impairment_loss_on_assets',
        'income_stat_fv_chg_income',
        'income_stat_investment_income',
        'income_stat_profit_from_operations',
        'income_stat_profit_before_tax',
        'income_stat_minus_income_tax_expenses',
        'income_stat_net_profit'
    ]
    
    df_common = df[cols].T
    df_common.columns = ['amount']
    df_common['common_size'] = df_common['amount'] / base
    df_common = df_common[['common_size']]

    col_map = {
        "income_stat_operating_income": "营业收入",
        "income_stat_operations_costs": "营业成本",
        "income_stat_operations_taxes_and_surcharges": "营业税金及附加",
        "income_stat_sales_fee": "销售费用",
        "income_stat_manage_fee": "管理费用",
        "income_stat_financial_expenses": "财务费用",
        "income_stat_impairment_loss_on_assets": "资产减值损失",
        "income_stat_fv_chg_income": "公允价值变动收益",
        "income_stat_investment_income": "投资收益",
        "income_stat_profit_from_operations": "营业利润",
        "income_stat_profit_before_tax": "利润总额",
        "income_stat_minus_income_tax_expenses": "所得税费用",
        "income_stat_net_profit": "净利润"
    }
    df_common = df_common.rename(index=col_map)
    return df_common
def filter_financials(df_single, filters=None):
    """
    根据给定过滤条件筛选财务同型分析结果。

    参数：
    ----------
    df_single : pd.DataFrame
        单只股票的同型分析结果（来自 txfx）
    filters : dict
        过滤条件字典，例如：
        {
            "净利润": (">", 0),
            "营业收入": (">", 1e8),
            "财务费用": ("<", 0.1)
        }

    返回：
    ----------
    bool
        True 表示通过过滤（保留）
        False 表示被过滤掉
    """
    if df_single is None or df_single.empty:
        return False

    if not filters:
        return True  # 没有过滤条件则默认保留

    for metric, (op, value) in filters.items():
        if metric not in df_single.index:
            continue  # 跳过不存在的指标
        val = df_single.loc[metric, "common_size"]
        if op == ">" and not (val > value):
            return False
        elif op == ">=" and not (val >= value):
            return False
        elif op == "<" and not (val < value):
            return False
        elif op == "<=" and not (val <= value):
            return False
        elif op == "==" and not (val == value):
            return False
        elif op == "!=" and not (val != value):
            return False
    return True

def txfx_industry(code, category_type='ci', date='20230801', statDate='2025q1', filters=None):
    import pandas as pd

    industry_stocks = get_stock_industry_stocks(code, category_type=category_type, date=date)
    if not industry_stocks:
        print("❌ 未找到行业成分股。")
        return None, None

    all_results = []
    log_records = []

    for s in industry_stocks:
        status, reason = "成功", ""
        try:
            df_single = txfx(s, statDate=statDate)
            if df_single is None or df_single.empty:
                status, reason = "失败", "无数据"
            elif not filter_financials(df_single, filters):
                status, reason = "过滤", "不符合过滤条件"
            else:
                df_single.columns = [s]
                all_results.append(df_single)
        except Exception as e:
            status, reason = "失败", str(e)
        log_records.append({"股票代码": s, "状态": status, "原因": reason})

    log_df = pd.DataFrame(log_records)

    if not all_results:
        print("🚫 所有成分股数据获取失败或被过滤。")
        return None, log_df

    df_all = pd.concat(all_results, axis=1)

    # 只保留数值型列（排除异常）
    numeric_df = df_all.select_dtypes(include='number')

    # 最大最小值及对应股票
    df_summary = pd.DataFrame({
        '平均数': numeric_df.mean(axis=1),
        '中位数': numeric_df.median(axis=1),
        '最大值': numeric_df.max(axis=1),
        '最小值': numeric_df.min(axis=1),
        '最大值股票': numeric_df.idxmax(axis=1),
        '最小值股票': numeric_df.idxmin(axis=1)
    })

    # 加上目标公司
    df_target = txfx(code, statDate=statDate)
    if df_target is not None:
        df_target.columns = ['本公司']
        df_summary = pd.concat([df_summary, df_target], axis=1)

    # 输出百分比格式
    display_df = df_summary.copy()
    for col in ['平均数','中位数','最大值','最小值','本公司']:
        if col in display_df.columns:
            display_df[col] = display_df[col].apply(lambda x: f"{x:.2%}" if pd.notnull(x) else "")

    print("\n📊 【行业同型分析汇总（含最大/最小值对应股票）】")
    print(display_df)

    return df_summary, log_df



filters = {
    "净利润": (">", 0)
}
txfx_industry('300033.SZ', category_type='ci', date='20230801', statDate='2025q1', filters=filters)

